/***************************************************************************
 创建者: 华磊
 开始时间: 2018.8.14
 copyright: (C) 华友高科
 修改说明: (每次有修改就添加一条，带有 修改人，修改时间，修改描述)
 example (1) hualei 2017.5.8 类的具体实现代码编写

 ***************************************************************************/
#include "taskmanager.h"
#include "GeneralDefine.h"


TaskManager::TaskManager(int robotIdIn)
{
    robotId=robotIdIn;
    //线程锁
    pthread_mutexattr_init(&taskMutexAttr);
    pthread_mutexattr_setprotocol(&taskMutexAttr,PTHREAD_PRIO_INHERIT);
    pthread_mutex_init(&taskMutex,&taskMutexAttr);

}

TaskManager::~TaskManager()
{
//    for(int i=0;i<taskThreadList.size();i++)
//    {
//        delete taskThreadList[i];
    //    }
}

int TaskManager::get_running_program_file_strings_task(int languageId, QString fileName,
                                                       QVector<QString> &programStrings)
{
    pthread_mutex_lock(&taskMutex);
    if(programEngineList.size())
    {
        for(int i = 0; i < programEngineList.size();i++)
        {

                int tmpResult=programEngineList[i].ProgramEnginePointer->get_running_program_file_strings(
                            languageId,fileName,programStrings);
                if(1==tmpResult)
                {
                    pthread_mutex_unlock(&taskMutex);
                    return 1;
                }

        }
    }
    pthread_mutex_unlock(&taskMutex);
    return -1;
}

int TaskManager::clearAllMsg()
{
    pthread_mutex_lock(&taskMutex);
    if(programEngineList.size())
    {
        for(int i = 0; i < programEngineList.size();i++)
        {
            if(NULL != programEngineList[i].ProgramEnginePointer)
            {
                qDebug() <<"====clearAllMsg=="<<i;
                programEngineList[i].ProgramEnginePointer->clearAllMsg_self();
            }
        }
    }
    pthread_mutex_unlock(&taskMutex);
    return 1;
}

int TaskManager::getCurrentRobotRunFile(CurrentRunFile &runRobotFile)
{
    int runnningTaskNum=getRunningTaskNumber();
    if(0==pthread_mutex_trylock(&taskMutex))
    {
        runRobotFile.runingFileName.resize(runnningTaskNum );
        runRobotFile.runningFileLine.resize(runnningTaskNum);

        vector <std::string> fileNameList;
        fileNameList.clear();
        bool isAllFinished=true;
        for(int tmpTaskIndex = 0;tmpTaskIndex < getRunningTaskNumber();tmpTaskIndex++)
        {
            runRobotFile.runingFileName[tmpTaskIndex ] =
                    programEngineList[tmpTaskIndex].fileName.toStdString();
            programEngineList[tmpTaskIndex].ProgramEnginePointer->lock();
            for(int programIndex = 0; programIndex < programEngineList[tmpTaskIndex].ProgramEnginePointer
                ->programUpdateDataList.programUpdateDataVector.size();programIndex++)
            {
                if(true == programEngineList[tmpTaskIndex].ProgramEnginePointer
                        ->programUpdateDataList.programUpdateDataVector[programIndex].runState)
                {
                    runRobotFile.runningFileLine[tmpTaskIndex ] =
                            programEngineList[tmpTaskIndex].ProgramEnginePointer
                            ->programUpdateDataList.programUpdateDataVector[programIndex].currentLineNum;
                    isAllFinished=false;
                }

                fileNameList.push_back(programEngineList[tmpTaskIndex].ProgramEnginePointer
                              ->programUpdateDataList.
                                       programUpdateDataVector[programIndex].programName.toStdString());

            }
            programEngineList[tmpTaskIndex].ProgramEnginePointer->unlock();
        }

        if(true==isAllFinished)
        {
    //        ->updateProgramSetRunInformation(0);
            runRobotFile.runingFileName.resize(1);
            runRobotFile.runningFileLine.resize(1);
            programEngineList[0].ProgramEnginePointer->lock();
            runRobotFile.runingFileName[0 ] = programEngineList[0].ProgramEnginePointer
                    ->programUpdateDataList.programUpdateDataVector[0].programName.toStdString();
            runRobotFile.runningFileLine[0] = programEngineList[0].ProgramEnginePointer
                    ->programUpdateDataList.programUpdateDataVector[0].currentLineNum;
            programEngineList[0].ProgramEnginePointer->unlock();
        }

        //sort(fileNameList.begin(),fileNameList.end());不要排序
        //唯一处理
        //vector<std::string>::iterator unique_iter = unique(fileNameList.begin(),fileNameList.end());
        //fileNameList.erase(unique_iter,fileNameList.end());

        runRobotFile.relatedFileName.resize(fileNameList.size());
        runRobotFile.relatedFileName = fileNameList;

        pthread_mutex_unlock(&taskMutex);
    }
    return 1;
}

int TaskManager::setAllTaskCease()
{
    pthread_mutex_lock(&taskMutex);
    if(programEngineList.size())
    {
        for(int i = 0; i < programEngineList.size();i++)
        {
            if(NULL != programEngineList[i].ProgramEnginePointer)
            {
//                qDebug() <<"====ceaseChildProgram=="<<i;
                programEngineList[i].ProgramEnginePointer->setTaskCeaseState();
            }
        }
    }
    pthread_mutex_unlock(&taskMutex);
    return 1;
}

int TaskManager::setAllTaskRun()
{
    pthread_mutex_lock(&taskMutex);
    if(programEngineList.size())
    {
        for(int i = 0; i < programEngineList.size();i++)
        {
            if(NULL != programEngineList[i].ProgramEnginePointer)
            {
                qDebug() <<"====setAllTaskRun=="<<i;
                programEngineList[i].ProgramEnginePointer->setTaskRunState();
            }
        }
    }
    pthread_mutex_unlock(&taskMutex);
    return 1;
}

int TaskManager::setAllTaskStop()
{
    pthread_mutex_lock(&taskMutex);
    if(programEngineList.size())
    {
        for(int i = 0; i < programEngineList.size();i++)
        {
            if(NULL != programEngineList[i].ProgramEnginePointer)
            {
//                qDebug() <<"====setAllTaskStop=="<<i;
                programEngineList[i].ProgramEnginePointer->setTaskStopState();
            }
        }
    }
    pthread_mutex_unlock(&taskMutex);
    return 1;
}

int TaskManager::addNewProgramEngine(ProgramEngineInfo programEngineInfo)
{
    pthread_mutex_lock(&taskMutex);
    programEngineList.append(programEngineInfo);
    pthread_mutex_unlock(&taskMutex);
    return 1;
}

int TaskManager::createNewProgramEngine(int fatherTaskIndex,int thisTaskIndex,RobotIo* ioControllerIn,
                                        RegData *mainRegData, RsrInfo *tmpRsrInfo)
{
    pthread_mutex_lock(&taskMutex);
    QThread *tmpThread;
    tmpThread=new QThread();

    ProgramEngine *newProgramEngine = new ProgramEngine(robotId,ioControllerIn,
                                 mainRegData,tmpRsrInfo,this,tmpThread,thisTaskIndex);


    QObject::connect(programEngineList[fatherTaskIndex].ProgramEnginePointer,
                     SIGNAL(childTaskOpenFile_signal(QString,int)),newProgramEngine,
                     SLOT(childTaskOpenFile_slot(QString,int)),Qt::QueuedConnection);


    QObject::connect(programEngineList[fatherTaskIndex].ProgramEnginePointer,
            SIGNAL(childTaskRun_signal(int)),newProgramEngine,
            SLOT(programEngineTaskLoop(int)),Qt::QueuedConnection);

    QObject::connect(programEngineList[fatherTaskIndex].ProgramEnginePointer,
            SIGNAL(setRunModel_signal(int)),newProgramEngine,
            SLOT(setRunModel_slot(int)),Qt::QueuedConnection);

    QObject::connect(programEngineList[fatherTaskIndex].ProgramEnginePointer,
            SIGNAL(setMoveType_signal(int)),newProgramEngine,
            SLOT(setMoveType_slot(int)),Qt::QueuedConnection);


    ProgramEngineInfo tmpEngineInfo;
    tmpEngineInfo.fileName="";
    tmpEngineInfo.ProgramEnginePointer=newProgramEngine;
    tmpEngineInfo.runningThread=tmpThread;
    tmpEngineInfo.state=E_TASK_ENGINE_FREE;
    programEngineList.append(tmpEngineInfo);
    pthread_mutex_unlock(&taskMutex);

    return 1;
}

int TaskManager::modifyProgramEningeFileName(int taskIndex,QString fileNameIn)
{
    pthread_mutex_lock(&taskMutex);
    programEngineList[taskIndex].fileName=fileNameIn;
    pthread_mutex_unlock(&taskMutex);
    return 1;
}

int TaskManager::getCurrentTaskSize()
{
    pthread_mutex_lock(&taskMutex);//死锁20190327
    int tmpSize=programEngineList.size();
    pthread_mutex_unlock(&taskMutex);
    return  tmpSize;
}

int TaskManager::runTask(int moveTypeIn, EN_CONTROL_TYPE runModelIn,
                         QString fileNameIn, int &taskIndexOut)
{
    pthread_mutex_lock(&taskMutex);
    for(int i=1;i<programEngineList.size();i++)
    {
        if(E_TASK_ENGINE_FREE==programEngineList[i].state)
        {
            taskIndexOut=i;
            programEngineList[0].ProgramEnginePointer->childTaskOpenFile
                    (fileNameIn,i);
            programEngineList[0].ProgramEnginePointer->childTaskRun(i);
            programEngineList[i].fileName=fileNameIn;
            programEngineList[i].state=E_TASK_ENGINE_RUNNING;
            programEngineList[i].ProgramEnginePointer->
                    initialParameter(moveTypeIn,runModelIn);
            pthread_mutex_unlock(&taskMutex);
            qDebug()<<"TaskManager::runTask sucess,fileNameIn="<<fileNameIn
                   <<",taskIndex="<<taskIndexOut;
            return 1;
        }
    }
    pthread_mutex_unlock(&taskMutex);
    return -1;
}

int TaskManager::resetTask()
{
    bool tmpIsInLoop=true;
    //0# task
    do
    {
        pthread_mutex_lock(&taskMutex);
        tmpIsInLoop=programEngineList[0].ProgramEnginePointer->isInRunningLoopStatus();
        pthread_mutex_unlock(&taskMutex);
        QCoreApplication::processEvents();
    }
    while(true==tmpIsInLoop);
    pthread_mutex_lock(&taskMutex);
    programEngineList[0].ProgramEnginePointer->restoreDefaultPogramSet();
    programEngineList[0].ProgramEnginePointer->getProgramSetRunFile(programEngineList[0].fileName);
    pthread_mutex_unlock(&taskMutex);

    //others# task
    tmpIsInLoop=true;
    pthread_mutex_lock(&taskMutex);
    int tmpSize=programEngineList.size();
    pthread_mutex_unlock(&taskMutex);
    for(int i=1;i<tmpSize;i++)
    {
        programEngineList[i].state=E_TASK_ENGINE_FREE;
        do
        {
            pthread_mutex_lock(&taskMutex);
            tmpIsInLoop=programEngineList[i].ProgramEnginePointer->isInRunningLoopStatus();
            pthread_mutex_unlock(&taskMutex);
            QCoreApplication::processEvents();
        }
        while(true==tmpIsInLoop);
        pthread_mutex_lock(&taskMutex);
        programEngineList[i].ProgramEnginePointer->resetAllProgramSet();
        pthread_mutex_unlock(&taskMutex);

    }
    return 1;
}



int TaskManager::getProgramEngineDebugInfo(int taskIndex,ProgramEngineDebugInfo &infoOut)
{
    pthread_mutex_lock(&taskMutex);
    programEngineList[taskIndex].ProgramEnginePointer->getDebugInfo(infoOut);
    pthread_mutex_unlock(&taskMutex);
    return 1;
}

int TaskManager::getTaskInfo(TaskManagerInfo &taskManagerInfo)
{
    pthread_mutex_lock(&taskMutex);
    int taskSize=programEngineList.size();
    taskManagerInfo.taskSize=taskSize;
    taskManagerInfo.taskThreadIsFinished.resize(taskSize);
    taskManagerInfo.taskThreadIsRunning.resize(taskSize);
    taskManagerInfo.runningLine.resize(taskSize);
    taskManagerInfo.runningThreadId.resize(taskSize);
    taskManagerInfo.fileName.resize(taskSize);
    taskManagerInfo.taskIndex.resize(taskSize);
    taskManagerInfo.state.resize(taskSize);
    taskManagerInfo.isInLoop.resize(taskSize);
    for(int i=0;i<programEngineList.size();i++)
    {
        taskManagerInfo.taskIndex[i]=i;
        taskManagerInfo.taskThreadIsFinished[i]=programEngineList[i].
                runningThread->isFinished();
        taskManagerInfo.taskThreadIsRunning[i]=programEngineList[i].
                runningThread->isRunning();
        taskManagerInfo.runningThreadId[i]=(long)programEngineList[i].
                runningThread->currentThreadId();
        taskManagerInfo.runningLine[i]=programEngineList[i].ProgramEnginePointer
                ->runningLineFloat;
        taskManagerInfo.fileName[i]=programEngineList[i]
                .fileName.toStdString();
        taskManagerInfo.state[i]=programEngineList[i]
                .state;
        taskManagerInfo.isInLoop[i]=programEngineList[i]
                .ProgramEnginePointer->isInRunningLoop;
    }
    pthread_mutex_unlock(&taskMutex);
    return 1;
}

int TaskManager::setRunModel(EN_CONTROL_TYPE runModelIn)
{
    pthread_mutex_lock(&taskMutex);
    for(int i=0;i<programEngineList.size();i++)
    {
        programEngineList[i].ProgramEnginePointer->setRunModel(runModelIn);

    }
    pthread_mutex_unlock(&taskMutex);
    return 1;
}

int TaskManager::setMoveType(int moveTypeIn)
{
    pthread_mutex_lock(&taskMutex);
    for(int i=0;i<programEngineList.size();i++)
    {
        programEngineList[i].ProgramEnginePointer->setMoveType(moveTypeIn);

    }
    pthread_mutex_unlock(&taskMutex);
    return 1;
}

int TaskManager::getRunningTaskNumber()
{
    int runningTask=0;
    for(int i=0;i<programEngineList.size();i++)
    {
        if(E_TASK_ENGINE_RUNNING==programEngineList[i].state)
        {
            runningTask++;
        }
    }

    return runningTask;
}





